// DesignPattern.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#ifndef CXX_DESIGNPATTERN_SINGLETON_H
#include "DESIGNPATTERN_Singleton.h"
#endif

#ifndef CXX_PROFESSION_H
#include "Profession.h"
#endif

#ifndef CXX_DESIGNPATTERN_SIMPLEFACTORY_H
#include "DESIGNPATTERN_SimpleFactory.h"
#endif

#ifndef CXX_DESIGNPATTERN_COMPLEXFACTORY_H
#include "DESIGNPATTERN_ComplexFactory.h"
#endif

#ifndef CXX_MOUSE_H
#include "Mouse.h"
#endif

#ifndef CXX_KEYBOARD_H
#include "Keyboard.h"
#endif

#ifndef CXX_MONITOR_H
#include "Monitor.h"
#endif

#ifndef CXX_HOST_H
#include "Host.h"
#endif

#ifndef CXX_COMPUTER_H
#include "Computer.h"
#endif

#ifndef CXX_DESIGNPATTERN_ABSTRACTFACTORY_H
#include "DESIGNPATTERN_AbstractFactory.h"
#endif

#ifndef CXX_DESIGNPATTERN_DIRECTOR_H
#include "DESIGNPATTERN_Director.h"
#endif

#ifndef CXX_DESIGNPATTERN_BUILDER_H
#include "DESIGNPATTERN_Builder.h"
#endif

#ifndef CXX_COMPUTER_H
#include "Computer.h"
#endif

#ifndef CXX_DESIGNPATTERN_PROTOTYPE_H
#include "DESIGNPATTERN_Prototype.h"
#endif

#ifndef CXX_DESIGNPATTERN_CONCRETEPROTOTYPE_H
#include "DESIGNPATTERN_ConcretePrototype.h"
#endif

#ifndef CXX_DESIGNPATTERN_BRIDGEIMP_H
#include "DESIGNPATTERN_BridgeImp.h"
#endif

#ifndef CXX_DESIGNPATTERN_BRIDGE_H
#include "DESIGNPATTERN_Bridge.h"
#endif

#ifndef CXX_DESIGNPATTERN_ADAPTEEJAPAN_H
#include "DESIGNPATTERN_AdapteeJapan.h"
#endif

#ifndef CXX_DESIGNPATTERN_TARGETCHINA_H
#include "DESIGNPATTERN_TargetChina.h"
#endif

#ifndef CXX_DESIGNPATTERN_ADAPTER_H
#include "DESIGNPATTERN_Adapter.h"
#endif

#ifndef CXX_DESIGNPATTERN_COMPUTERCOMPONENT_H
#include "DESIGNPATTERN_ComputerComponent.h"
#endif

#ifndef CXX_DESIGNPATTERN_DECORATOR_H
#include "DESIGNPATTERN_Decorator.h"
#endif

#ifndef CXX_DESIGNPATTERN_ENTRY_H
#include "DESIGNPATTERN_Entry.h"
#endif

#ifndef CXX_DESIGNPATTERN_DIRECTORY_H
#include "DESIGNPATTERN_Directory.h"
#endif

#ifndef CXX_DESIGNPATTERN_FILE_H
#include "DESIGNPATTERN_File.h"
#endif

#ifndef CXX_DESIGNPATTERN_FLYWEIGHTFACTORY_H
#include "DESIGNPATTERN_FlyweightFactory.h"
#endif

#ifndef CXX_DESIGNPATTERN_FLYWEIGHT_H
#include "DESIGNPATTERN_Flyweight.h"
#endif

#ifndef CXX_DESIGNPATTERN_CONCRETEFLYWEIGHT_H
#include "DESIGNPATTERN_ConcreteFlyweight.h"
#endif

#ifndef CXX_DESIGNPATTERN_FACADE_H
#include "DESIGNPATTERN_Facade.h"
#endif

int _tmain(int argc, _TCHAR* argv[])
{
#if DEBG_TEST_SINGLETON
	cout << endl << endl;
	cout<<"***************************Singleton***************************"<<endl;
	Singleton* pSingletonA = NULL;
	Singleton* pSingletonB =  NULL;
	
	pSingletonA = Singleton::Instance();
	pSingletonB = Singleton::Instance();

	Singleton::Destroy();
	Singleton::Destroy();
#endif

#if DEBG_TEST_SIMPLEFACTORY
	cout << endl << endl;
	cout<<"***************************SimpleFactory***************************"<<endl;
	Profession* pSimpleFactoryProfession[PROFESSION_ALL] =  {0};
	SimpleFactory* pSimpleFactory = SimpleFactory::Instance();
	for (int i= PROFESSION_NONE; i < PROFESSION_ALL; i++) {
		pSimpleFactoryProfession[i] = pSimpleFactory->CreateProfession(static_cast<PROFESSION_TYPE>(i));
	}

	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		if (NULL != pSimpleFactoryProfession[i]) {
			pSimpleFactoryProfession[i]->Operation();
		}
	}

	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		if (NULL != pSimpleFactoryProfession[i]) {
			delete pSimpleFactoryProfession[i];
			pSimpleFactoryProfession[i] = NULL;
		}
	}
	SimpleFactory::Destroy();
	pSimpleFactory = NULL;
#endif

#if DEBG_TEST_COMPLEXFACTORY
	cout << endl << endl;
	cout<<"***************************ComplexFactory***************************"<<endl;
	ComplexFactory* pComplexFactory[PROFESSION_ALL] = {0};
	pComplexFactory[PROFESSION_WARRIOR] = WarriorFactory::Instance();
	pComplexFactory[PROFESSION_MASTER] = MasterFactory::Instance();
	pComplexFactory[PROFESSION_PRIEST] = PriestFactory::Instance();
	Profession* pComplexFactoryProfession[PROFESSION_ALL] = { 0 };
	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		if (NULL != pComplexFactory[i]) {
			pComplexFactoryProfession[i] = pComplexFactory[i]->CreateProfession();
		}
	}

	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		if (NULL != pComplexFactoryProfession[i]) {
			pComplexFactoryProfession[i]->Operation();
		}
	}

	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		if (NULL != pSimpleFactoryProfession[i]) {
			delete pSimpleFactoryProfession[i];
			pSimpleFactoryProfession[i] = NULL;
		}
	}
	WarriorFactory::Destroy();
	MasterFactory::Destroy();
	PriestFactory::Destroy();
	for (int i = PROFESSION_NONE + 1; i < PROFESSION_ALL; i++) {
		pComplexFactory[i] = NULL;
	}
#endif


#if DEBG_TEST_ABSTRACTFACTORY
	cout << endl << endl;
	cout<<"***************************AbstractFactory***************************"<<endl;
	AbstractFactory* pAbstractFactory[MANUFACTURER_ALL] = { 0 };
	pAbstractFactory[MANUFACTURER_DELL] = DELLFactory::Instance();
	pAbstractFactory[MANUFACTURER_ASUS] = ASUSFactory::Instance();
	pAbstractFactory[MANUFACTURER_HP] = HPFactory::Instance();
	pAbstractFactory[MANUFACTURER_MIX] = MIXFactory::Instance();
	AbstractComputer* pAbstractFactoryAbstractComputer[MANUFACTURER_ALL] = { 0 };
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractFactory[i]) {
			pAbstractFactoryAbstractComputer[i] = pAbstractFactory[i]->CreateDesktopComputerNormal();
		}
	}
	
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractFactoryAbstractComputer[i]) {
			pAbstractFactoryAbstractComputer[i]->Operation();
		}
	}

	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractFactoryAbstractComputer[i]) {
			delete pAbstractFactoryAbstractComputer[i];
			pAbstractFactoryAbstractComputer[i] = NULL;
		}
	}

	DELLFactory::Destroy();
	ASUSFactory::Destroy();
	HPFactory::Destroy();
	MIXFactory::Destroy();
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractFactory[i]) {
			pAbstractFactory[i] = NULL;
		}
	}
#endif

#if DEBG_TEST_BUILDER
	cout << endl << endl;
	cout<<"***************************Builder***************************"<<endl;
	Builder* pBuilder[MANUFACTURER_ALL] = { 0 };
	pBuilder[MANUFACTURER_DELL] = DELLBuilder::Instance();
	pBuilder[MANUFACTURER_ASUS] = ASUSBuilder::Instance();
	pBuilder[MANUFACTURER_HP] = HPBuilder::Instance();
	Director* pDirector[COMPUTER_ALL][COMPUTERPART_ALL][MANUFACTURER_ALL] = { 0 };
	//notebook
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_NOTEBOOK][COMPUTERPART_NORMAL][i] = new NotebookDirectorNormal(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_NOTEBOOK][COMPUTERPART_DOUBLEMOUSE][i] = new NotebookDirectorDoubleMouse(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_NOTEBOOK][COMPUTERPART_DOUBLEKEYBOARD][i] = new NotebookDirectorDoubleKeyboard(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_NOTEBOOK][COMPUTERPART_DOUBLEMONITOR][i] = new NotebookDirectorDoubleMonitor(pBuilder[i]);
	}
	//desktop
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_DESKTOP][COMPUTERPART_NORMAL][i] = new DesktopDirectorNormal(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_DESKTOP][COMPUTERPART_DOUBLEMOUSE][i] = new DesktopDirectorDoubleMouse(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_DESKTOP][COMPUTERPART_DOUBLEKEYBOARD][i] = new DesktopDirectorDoubleKeyboard(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_DESKTOP][COMPUTERPART_DOUBLEMONITOR][i] = new DesktopDirectorDoubleMonitor(pBuilder[i]);
	}
	//server
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_SERVER][COMPUTERPART_NORMAL][i] = new ServerDirectorNormal(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_SERVER][COMPUTERPART_DOUBLEMOUSE][i] = new ServerDirectorDoubleMouse(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_SERVER][COMPUTERPART_DOUBLEKEYBOARD][i] = new ServerDirectorDoubleKeyboard(pBuilder[i]);
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		pDirector[COMPUTER_SERVER][COMPUTERPART_DOUBLEMONITOR][i] = new ServerDirectorDoubleMonitor(pBuilder[i]);
	}
	
	AbstractComputer* pBuiderAbstractComputer[COMPUTER_ALL][COMPUTERPART_ALL][MANUFACTURER_ALL] = { 0 };
	for (int i = COMPUTER_NONE + 1; i < COMPUTER_ALL; i++) {
		for (int j = COMPUTERPART_NONE + 1; j < COMPUTERPART_ALL; j++) {
			for (int l = MANUFACTURER_NONE + 1; l < MANUFACTURER_ALL; l++) {
				if (NULL != pDirector[i][j][l]) {
					pBuiderAbstractComputer[i][j][l] = pDirector[i][j][l]->CreateAbstractComputer();
				}
			}
		}
	}

	for (int i = COMPUTER_NONE + 1; i < COMPUTER_ALL; i++) {
		for (int j = COMPUTERPART_NONE + 1; j < COMPUTERPART_ALL; j++) {
			for (int l = MANUFACTURER_NONE + 1; l < MANUFACTURER_ALL; l++) {
				if (NULL != pBuiderAbstractComputer[i][j][l]) {
					pBuiderAbstractComputer[i][j][l]->Operation();
				}
			}
		}
	}

	for (int i = COMPUTER_NONE + 1; i < COMPUTER_ALL; i++) {
		for (int j = COMPUTERPART_NONE + 1; j < COMPUTERPART_ALL; j++) {
			for (int l = MANUFACTURER_NONE + 1; l < MANUFACTURER_ALL; l++) {
				if (NULL != pBuiderAbstractComputer[i][j][l]) {
					delete pBuiderAbstractComputer[i][j][l];
					pBuiderAbstractComputer[i][j][l] = NULL;
				}
			}
		}
	}

	for (int i = COMPUTER_NONE + 1; i < COMPUTER_ALL; i++) {
		for (int j = COMPUTERPART_NONE + 1; j < COMPUTERPART_ALL; j++) {
			for (int l = MANUFACTURER_NONE + 1; l < MANUFACTURER_ALL; l++) {
				if (NULL != pDirector[i][j][l]) {
					delete pDirector[i][j][l];
					pDirector[i][j][l] = NULL;
				}
			}
		}
	}

	DELLBuilder::Destroy();
	ASUSBuilder::Destroy();
	HPBuilder::Destroy();
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pBuilder[i]) {
			pBuilder[i] = NULL;
		}
	}
#endif

#if DEBG_TEST_PROTOTYPE
	cout << endl << endl;
	cout<<"***************************DEBG_TEST_PROTOTYPE***************************"<<endl;

	Prototype* pPrototype = new ConcretePrototype;
	Prototype* pPrototypeTemp = pPrototype->Clone();
	
	if (NULL != pPrototype) {
		delete pPrototype;
		pPrototype = NULL;
	}
	if (NULL != pPrototypeTemp) {
		delete pPrototypeTemp;
		pPrototypeTemp = NULL;
	}
#endif

#if DEBG_TEST_BRIDGE
	cout << endl << endl;
	cout << "***************************DEBG_TEST_BRIDGE***************************" << endl;
	AbstractBridgeImp* pAbstractBridgeImp[MANUFACTURER_ALL] = { 0 };
	pAbstractBridgeImp[MANUFACTURER_DELL] = new DELLBridgeImp;
	pAbstractBridgeImp[MANUFACTURER_ASUS] = new ASUSBridgeImp;
	pAbstractBridgeImp[MANUFACTURER_HP] = new HPBridgeImp;
	AbstractBridge* pAbstractBridge[MANUFACTURER_ALL][COMPUTER_ALL] = { 0 };
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractBridgeImp[i]) {
			pAbstractBridge[i][COMPUTER_NOTEBOOK] = new NotebookBridge(pAbstractBridgeImp[i]);
			pAbstractBridge[i][COMPUTER_DESKTOP] = new DesktopBridge(pAbstractBridgeImp[i]);
			pAbstractBridge[i][COMPUTER_SERVER] = new ServerBridge(pAbstractBridgeImp[i]);
		}
	}

	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		for (int j = COMPUTER_NONE + 1; j < COMPUTER_ALL; j++) {
			if (NULL != pAbstractBridge[i][j]) {
				pAbstractBridge[i][j]->Operation();
			}
		}
	}
	
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		for (int j = COMPUTER_NONE + 1; j < COMPUTER_ALL; j++) {
			if (NULL != pAbstractBridge[i][j]) {
				delete pAbstractBridge[i][j];
				pAbstractBridge[i][j] = NULL;
			}
		}
	}
	for (int i = MANUFACTURER_NONE + 1; i < MANUFACTURER_ALL; i++) {
		if (NULL != pAbstractBridgeImp[i]) {
			delete pAbstractBridgeImp[i];
			pAbstractBridgeImp[i] = NULL;
		}
	}
#endif

#ifdef DEBG_TEST_ADAPTER
	cout << endl << endl;
	cout << "***************************DEBG_TEST_ADAPTER***************************" << endl;

	AdapteeJapan* pAdapteeJapan = new AdapteeJapan;
	TargetChina* pTargetChina = new Adapter(pAdapteeJapan);
	pTargetChina->Voltage220V();

	if (NULL != pTargetChina) {
		delete pTargetChina;
		pTargetChina = NULL;
	}

	if (NULL != pAdapteeJapan) {
		delete pAdapteeJapan;
		pAdapteeJapan = NULL;
	}
#endif

#ifdef DEBG_TEST_DECORATOR
	cout << endl << endl;
	cout << "***************************DEBG_TEST_DECORATOR***************************" << endl;

	ComputerComponent* pComputerComponent[COMPUTER_ALL] = { 0 };
	pComputerComponent[COMPUTER_DESKTOP] = new DesktopComponent;
	Decorator* pASUSDecorator = new ASUSDecorator(pComputerComponent[COMPUTER_DESKTOP]);
	pASUSDecorator->Operation();
	Decorator* pASUSDecorato_DELL = new DELLDecorator(pASUSDecorator);
	pASUSDecorato_DELL->Operation();
	Decorator* pASUSDecorato_DELL_HP = new HPDecorator(pASUSDecorato_DELL);
	pASUSDecorato_DELL_HP->Operation();

	if (NULL != pASUSDecorato_DELL_HP) {
		delete pASUSDecorato_DELL_HP;
		pASUSDecorato_DELL_HP = NULL;
	}
	if (NULL != pASUSDecorato_DELL) {
		delete pASUSDecorato_DELL;
		pASUSDecorato_DELL = NULL;
	}
	if (NULL != pASUSDecorator) {
		delete pASUSDecorator;
		pASUSDecorator = NULL;
	}
	if (NULL != pASUSDecorator) {
		delete pASUSDecorator;
		pASUSDecorator = NULL;
	}

	for (int i = COMPUTER_NONE + 1; i < COMPUTER_ALL; i++) {
		if (NULL != pComputerComponent[i]) {
			delete pComputerComponent[i];
			pComputerComponent[i] = NULL;
		}
	}
#endif
	
#ifdef DEBG_TEST_COMPOSITE
	cout << endl << endl;
	cout << "***************************DEBG_TEST_COMPOSITE***************************" << endl;

	Entry* pPictures = new Directory("Pictures", 0);
	Entry* pWallpagers = new Directory("Wallpagers", 0);
	Directory* pDirectory = NULL;
	if (Entry::ENTRY_DIRECTORY == pPictures->GetEntry()) {
		pDirectory = dynamic_cast<Directory*>(pPictures);
		pDirectory->Add(pWallpagers);
	}
	Entry* pWallpager1 = new File("wallpager1.jpg", 1024);
	Entry* pWallpager2 = new File("wallpager2.jpg", 512);
	Entry* pWallpager3 = new File("wallpager3.jpg", 256);
	Entry* pWallpager4 = new File("wallpager4.jpg", 64);
	if (Entry::ENTRY_DIRECTORY == pWallpagers->GetEntry()) {
		pDirectory = dynamic_cast<Directory*>(pWallpagers);
		pDirectory->Add(pWallpager1);
		pDirectory->Add(pWallpager2);
		pDirectory->Add(pWallpager3);
		pDirectory->Add(pWallpager4);
	}
	if (NULL != pPictures) {
		delete pPictures;
		pPictures = NULL;
	}
#endif

#ifdef DEBG_TEST_FLYWEIGHT
	cout << endl << endl;
	cout << "***************************DEBG_TEST_FLYWEIGHT***************************" << endl;

	FlyweightFactory* pFlyweightFactory = FlyweightFactory::Instance();
	Flyweight* fw1 = pFlyweightFactory->CreateFlyweight("hello");
	Flyweight* fw2 = pFlyweightFactory->CreateFlyweight("world!");
	Flyweight* fw3 = pFlyweightFactory->CreateFlyweight("hello");
	FlyweightFactory::Destroy();
#endif

#ifdef DEBG_TEST_FACADE
	cout << endl << endl;
	cout << "***************************DEBG_TEST_FACADE***************************" << endl;

	Facade* pFacade = Facade::Instance();
	pFacade->OperationWrapper();
	Facade::Destroy();
#endif

	return 0;
}

